﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace XmlVisualizer.Controls
{
    /// <summary>
    /// Custom control - EditableTextBlock.
    /// </summary>
    [TemplatePart(Type = typeof(Grid), Name = EditableTextBlock.GRID_NAME)]
    [TemplatePart(Type = typeof(TextBlock), Name = EditableTextBlock.TEXTBLOCK_DISPLAYTEXT_NAME)]
    [TemplatePart(Type = typeof(TextBox), Name = EditableTextBlock.TEXTBOX_EDITTEXT_NAME)]
    public class EditableTextBlock : Control
    {
        #region Constants
        private const string GRID_NAME = "PART_GridContainer";
        private const string TEXTBLOCK_DISPLAYTEXT_NAME = "PART_TbDisplayText";
        private const string TEXTBOX_EDITTEXT_NAME = "PART_TbEditText";
        #endregion

        #region Member Fields
        private Grid m_GridContainer;
        private TextBlock m_TextBlockDisplayText;
        private TextBox m_TextBoxEditText;
        #endregion

        #region Properties
        /// <summary>
        /// Gets the TextBlock part of this control.
        /// </summary>
        public TextBlock TextBlockPart
        {
            get { return m_TextBlockDisplayText; }
        }

        /// <summary>
        /// Gets the TextBox part of this control.
        /// </summary>
        public TextBox TextBoxPart
        {
            get { return m_TextBoxEditText; }
        }
        #endregion

        #region Dependency Properties
        /// <summary>
        /// Gets or sets the AcceptsReturnProperty.
        /// </summary>
        public bool AcceptsReturn
        {
            get { return (bool)GetValue(AcceptsReturnProperty); }
            set { SetValue(AcceptsReturnProperty, value); }
        }
        /// <summary>
        /// Identifies the AcceptsReturnProperty.
        /// </summary>
        public static readonly DependencyProperty AcceptsReturnProperty = DependencyProperty.Register("AcceptsReturn",
            typeof(bool), typeof(EditableTextBlock), new FrameworkPropertyMetadata(false));

        /// <summary>
        /// Gets or sets the TextProperty.
        /// </summary>
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
        /// <summary>
        /// Identifies the XmlVisualizer.Controls.EditableTextBlock.TextProperty.
        /// </summary>
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text",
            typeof(string), typeof(EditableTextBlock), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        /// <summary>
        /// Gets or sets the TextBlockForegroundColorProperty.
        /// </summary>
        public Brush TextBlockForegroundColor
        {
            get { return (Brush)GetValue(TextBlockForegroundColorProperty); }
            set { SetValue(TextBlockForegroundColorProperty, value); }
        }

        /// <summary>
        /// Identifies the XmlVisualizer.Controls.EditableTextBlock.TextBlockForegroundColorProperty.
        /// </summary>
        public static readonly DependencyProperty TextBlockForegroundColorProperty = DependencyProperty.Register("TextBlockForegroundColor",
            typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(TextBlock.ForegroundProperty.DefaultMetadata.DefaultValue));

        /// <summary>
        /// Gets or sets the TextBlockBackgroundColorProperty.
        /// </summary>
        public Brush TextBlockBackgroundColor
        {
            get { return (Brush)GetValue(TextBlockBackgroundColorProperty); }
            set { SetValue(TextBlockBackgroundColorProperty, value); }
        }

        /// <summary>
        /// Identifies the XmlVisualizer.Controls.EditableTextBlock.TextBlockBackgroundColorProperty.
        /// </summary>
        public static readonly DependencyProperty TextBlockBackgroundColorProperty = DependencyProperty.Register("TextBlockBackgroundColor",
            typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(TextBlock.BackgroundProperty.DefaultMetadata.DefaultValue));

        /// <summary>
        /// Gets or sets the TextBoxForegroundColorProperty.
        /// </summary>
        public Brush TextBoxForegroundColor
        {
            get { return (Brush)GetValue(TextBoxForegroundColorProperty); }
            set { SetValue(TextBoxForegroundColorProperty, value); }
        }

        /// <summary>
        /// Identifies the XmlVisualizer.Controls.EditableTextBlock.TextBoxForegroundColorProperty.
        /// </summary>
        public static readonly DependencyProperty TextBoxForegroundColorProperty = DependencyProperty.Register("TextBoxForegroundColor",
            typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(TextBox.ForegroundProperty.DefaultMetadata.DefaultValue));

        /// <summary>
        /// Gets or sets the TextBoxBackgroundColorProperty.
        /// </summary>
        public Brush TextBoxBackgroundColor
        {
            get { return (Brush)GetValue(TextBoxBackgroundColorProperty); }
            set { SetValue(TextBoxBackgroundColorProperty, value); }
        }

        /// <summary>
        /// Identifies the XmlVisualizer.Controls.EditableTextBlock.TextBoxBackgroundColorProperty.
        /// </summary>
        public static readonly DependencyProperty TextBoxBackgroundColorProperty = DependencyProperty.Register("TextBoxBackgroundColor",
            typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(TextBox.BackgroundProperty.DefaultMetadata.DefaultValue));
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes the EditableTextBlock class.
        /// </summary>
        static EditableTextBlock()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(EditableTextBlock), new FrameworkPropertyMetadata(typeof(EditableTextBlock)));
        }
        #endregion

        #region Overrides Methods
        /// <summary>
        /// Invoked when applying template.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.m_GridContainer = this.Template.FindName(GRID_NAME, this) as Grid;
            if (this.m_GridContainer != null)
            {
                this.m_TextBlockDisplayText = this.m_GridContainer.Children[0] as TextBlock;
                this.m_TextBoxEditText = this.m_GridContainer.Children[1] as TextBox;
                this.m_TextBoxEditText.LostFocus += this.OnTextBoxLostFocus;
            }
        }

        /// <summary>
        /// Invoked on MouseDoubleClick.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            base.OnMouseDoubleClick(e);
            this.m_TextBlockDisplayText.Visibility = Visibility.Hidden;
            this.m_TextBoxEditText.Visibility = Visibility.Visible;
            this.m_TextBoxEditText.Focus();
            this.m_TextBoxEditText.SelectAll();
            e.Handled = true;
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Invoked when m_TextBoxEdit loses focus.
        /// </summary>
        /// <param name="sender">The object where the event handler is attached.</param>
        /// <param name="e">The event data.</param>
        private void OnTextBoxLostFocus(object sender, RoutedEventArgs e)
        {
            this.m_TextBlockDisplayText.Visibility = Visibility.Visible;
            this.m_TextBoxEditText.Visibility = Visibility.Hidden;
        }
        #endregion
    }
}